# bootstrap_utils.pm
# Copyright (C) 2006, 2007  Stephane Alnet
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

package CCNCore::bootstrap_utils;
use strict; use warnings;
use CCN::Text;
use CCNCore::Home;

sub identify_one_interface($)
{
    my ($ifname) = @_;
    open(my $fh, "set -e; export LANG=C; /sbin/ifconfig $ifname 2>/dev/null |") or die $!;

    my $env = {};
    while(<$fh>)
    {
        chomp;
        $env->{ifname} = $1, $env->{mac} = CCN::Text::qr_mac_clean($2), next
            if /^\s*(eth\d)\s+Link encap:Ethernet\s+HWaddr\s+([\dA-Fa-f:]+)\s*$/;
        $env->{ipnet_ip} = $1, $env->{ipnet_mask} = $3, next
            if /^\s*inet addr:([\d.]+)\s+Bcast:([\d.]+)\s+Mask:([\d.]+)\s*$/;
    }
    close($fh);

    return undef if not exists $env->{mac};

    print "CCN: Found interface $env->{ifname} with MAC $env->{mac} and ".
        (exists $env->{ipnet_ip} ? "IP address $env->{ipnet_ip}/$env->{ipnet_mask}" : "no IP address").
        ".\n";

    return $env
        if exists $env->{mac} and not exists $env->{ipnet_ip};

    # If it has an IP address and no other interface is already the primary...
    unless (-e CCNCore::Home::config.'/local/my-mac')
    {
        print_to CCNCore::Home::config.'/local/my-mac', $env->{mac};
        # See primary_ip in CCN::Base
        $env->{rank} = 1;
    }

    return $env;
}

sub identify_interfaces($)
{
    my $env         = shift;
    my @ifnames = qw(eth0 eth1 eth2 eth3 eth4);
    my $rank = 2;
    for my $i (0..$#ifnames)
    {
        my $env2 = identify_one_interface($ifnames[$i]);
        if(defined $env2)
        {
            $env2->{rank} = $rank++ if not exists $env2->{rank};
            $env->{interfaces}->{$env2->{ifname}} = $env2;
        }
    }
}

sub guess_os()
{
    # We try to guess the OS. Supported models are:
    #   CentOS
    #   Debian
    #   Fedora Core

    # Example outputs:
    #   Fedora Core release 1.92 (FC2 Test 3)
    #   CentOS release 4.4 (Final)
    #   Debian testing/unstable
    #   CarrierClass.net 2.0

    # Redhat-based, including CentOS
    return content_of '/etc/redhat-release' if -e '/etc/redhat-release';
    # CarrierClass.net OS (Debian base)
    return 'CarrierClass.net '.content_of('/etc/ccn_version') if -e '/etc/ccn_version';
    # Other Debian
    return 'Debian '.content_of('/etc/debian_version') if -e '/etc/debian_version';

    die 'CCN Error: Unknown or unsupported Operating System';
}

sub identify_os($)
{
    my ($env) = @_;

    my $os = guess_os();
    $os =~ s/\s.*$//;
    $os = lc($os);
    chomp $os;

    $env->{'os'} = $os;
}

sub identify_default_route($)
{
    my ($env) = @_;
    my $sql = '';
    open(my $fh, '/bin/netstat -rn |') or die $!;
    while(<$fh>)
    {
        chomp;
        next unless /^0.0.0.0\s/;
        my @v = split;
        $env->{default_router} = $v[1];
        last;
    }
    close($fh);
}

sub generate_keypair()
{
    use CCNCore::Scripting;
    CCN::Scripting::exec_command(CCNCore::Home::manager.'/lib/CCNCore/bin/bootstrap/generate-keypair.sh');
}

sub identify_node()
{
    my $env = {};
    identify_interfaces($env);
    identify_os($env);
    identify_default_route($env);
    generate_keypair();
    return $env;
}

1;
